/**********************************************************
 *
 * websocket通信管理，通信协议定义
 * *********************************************************/

import { CSocket } from 'src/socket/websocket';
import { CVariableDataItem, CDeviceDataItem } from 'stores/editorModels';


//帧头
const WS_FRAME_HEADER = 0x7789;

//定义命令符
export enum EnumWSCommand {
  WS_NULL = 0,
  WS_CERTIFY_USER = 0x5001,
  WS_REGISTER_DEVICE = 0x5002,
  WS_REGISTER_VARIABLE = 0x5003,
  WS_READ_DEV_CONNECTION = 0x6001,

  WS_READ_VARIABLE = 0x9001,
  WS_WRITE_VARIABLE = 0x9002,

  WS_ERR_CODE = 0xA001
}


export function useScadaPacket () {
  //账号校验
  const wsCertifyUser = (ws:CSocket, username: string, password: string, projectId: number) => {
    let ofs = 0;
    let t = 0;
    let size = 4 + username.length + password.length + 4;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);


    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_CERTIFY_USER >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_CERTIFY_USER & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //username长度
    t = username.length;
    view.setUint8(ofs++, (t >> 8) & 0xFF);
    view.setUint8(ofs++, t & 0xFF);

    //password长度
    t = password.length;
    view.setUint8(ofs++, (t >> 8) & 0xFF);
    view.setUint8(ofs++, t & 0xFF);

    //username
    //console.log(username);
    let encoder = new TextEncoder();
    //字符串转Uint8Array
    let uint8Arr = encoder.encode(username);
    for (let i = 0; i < username.length; i++) {
      view.setUint8(ofs++, uint8Arr[i]);
    }

    //password
    uint8Arr = encoder.encode(password);
    for (let i = 0; i < password.length; i++) {
      view.setUint8(ofs++, uint8Arr[i]);
    }

    //projectId
    t = projectId;
    view.setUint8(ofs++, (t >> 24) & 0xFF);
    view.setUint8(ofs++, (t >> 16) & 0xFF);
    view.setUint8(ofs++, (t >> 8) & 0xFF);
    view.setUint8(ofs++, t & 0xFF);

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }

  //像服务器注册变量
  const wsRegisterVariable = (ws:CSocket, varList: CVariableDataItem[]) => {
    let ofs = 0;
    let t = 0;
    let size = varList.length * 4;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);

    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_REGISTER_VARIABLE >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_REGISTER_VARIABLE & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //变量
    for (let i = 0; i < varList.length; i++) {
      t = varList[i].varId;
      view.setUint8(ofs++, (t >> 24) & 0xFF);
      view.setUint8(ofs++, (t >> 16) & 0xFF);
      view.setUint8(ofs++, (t >> 8) & 0xFF);
      view.setUint8(ofs++, t & 0xFF);
    }

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }

  //从服务器读取变量值
  const wsReadVariable = (ws:CSocket, varList: CVariableDataItem[]) => {
    let ofs = 0;
    let t = 0;
    let size = varList.length * 4;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);

    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_READ_VARIABLE >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_READ_VARIABLE & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //变量
    for (let i = 0; i < varList.length; i++) {
      t = varList[i].varId;
      view.setUint8(ofs++, (t >> 24) & 0xFF);
      view.setUint8(ofs++, (t >> 16) & 0xFF);
      view.setUint8(ofs++, (t >> 8) & 0xFF);
      view.setUint8(ofs++, t & 0xFF);
    }

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }

  //下发控制命令,vid为变量ID
  const wsWriteVariable = (ws:CSocket, varId: number, vData: number) => {
    let ofs = 0;
    let size = 6;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);

    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_WRITE_VARIABLE >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_WRITE_VARIABLE & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //变量
    view.setUint8(ofs++, (varId >> 24) & 0xFF);
    view.setUint8(ofs++, (varId >> 16) & 0xFF);
    view.setUint8(ofs++, (varId >> 8) & 0xFF);
    view.setUint8(ofs++, varId & 0xFF);

    //数值
    view.setUint8(ofs++, (vData >> 8) & 0xFF);
    view.setUint8(ofs++, vData & 0xFF);

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }


  //像服务器注册设备，自动发送连接信息
  const wsRegisterDevice = (ws:CSocket, devList: CDeviceDataItem[]) => {
    let ofs = 0;
    let t = 0;
    let size = devList.length * 4;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);

    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_REGISTER_DEVICE >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_REGISTER_DEVICE & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //设备ID
    for (let i = 0; i < devList.length; i++) {
      t = devList[i].devId;
      view.setUint8(ofs++, (t >> 24) & 0xFF);
      view.setUint8(ofs++, (t >> 16) & 0xFF);
      view.setUint8(ofs++, (t >> 8) & 0xFF);
      view.setUint8(ofs++, t & 0xFF);
    }

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }

  //像服务器注册设备，自动发送连接信息
  const wsReadDeviceConnection = (ws:CSocket, devList: CDeviceDataItem[]) => {
    let ofs = 0;
    let t = 0;
    let size = devList.length * 4;
    let buffer = new ArrayBuffer(6 + size);
    let view = new DataView(buffer);

    //帧头
    view.setUint8(ofs++, (WS_FRAME_HEADER >> 8) & 0xFF);
    view.setUint8(ofs++, WS_FRAME_HEADER & 0xFF);

    //默认为大端法
    view.setUint8(ofs++, (EnumWSCommand.WS_READ_DEV_CONNECTION >> 8) & 0xFF);
    view.setUint8(ofs++, EnumWSCommand.WS_READ_DEV_CONNECTION & 0xFF);
    view.setUint8(ofs++, (size >> 8) & 0xFF);
    view.setUint8(ofs++, size & 0xFF);

    //设备ID
    for (let i = 0; i < devList.length; i++) {
      t = devList[i].devId;
      view.setUint8(ofs++, (t >> 24) & 0xFF);
      view.setUint8(ofs++, (t >> 16) & 0xFF);
      view.setUint8(ofs++, (t >> 8) & 0xFF);
      view.setUint8(ofs++, t & 0xFF);
    }

    //转换为普通数组
    ws.send(Array.from(new Uint8Array(buffer)));
  }

  return {
    WS_FRAME_HEADER,
    EnumWSCommand,
    wsCertifyUser,
    wsRegisterVariable,
    wsReadVariable,
    wsWriteVariable,
    wsRegisterDevice,
    wsReadDeviceConnection
  };
}
